﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Office.Tools.Ribbon;
using System.Globalization;
using System.Windows.Forms;
using System.IO;

namespace Europrog.Office.Excel.ResXHandler
{
    using Excel = Microsoft.Office.Interop.Excel;
    using Europrog.Windows.Resx2xlsx.ServiceLogic;
    using System.Reflection;


    public partial class ResXConverter
    {
        private static readonly string APPLICATION_NAME="Resx Converter";
        private IList<string> CultureNames;
        private Excel.Worksheet RootResource;
        private string RootResourceFileName;
        private string RootResourceFile;

        private void ResXConverter_Load(object sender, RibbonUIEventArgs e)
        {
            SetResourceStrings();
            CultureNames = new List<string>();
            SetCultureNames();
            EnableButtons();
        }

        private void SetCultureNames()
        {
            dropDownCultureNames.Items.Clear();
            foreach (var item in System.Globalization.CultureInfo.GetCultures(CultureTypes.NeutralCultures).OrderBy(p => p.DisplayName).ToList())
            {
                if (!CultureNames.Contains(item.TextInfo.CultureName))
                {
                    RibbonDropDownItem ribbonDropdownItem = CreateRibbonDropDownItem();
                    ribbonDropdownItem.Label = string.Format("{0} - {1} ({2})", item.DisplayName, item.TextInfo.CultureName, item.NativeName);
                    ribbonDropdownItem.Tag = item.TextInfo.CultureName;
                    dropDownCultureNames.Items.Add(ribbonDropdownItem);
                }
            }
        }

        private RibbonDropDownItem CreateRibbonDropDownItem()
        {
            return this.Factory.CreateRibbonDropDownItem();
        }

        private void SetResourceStrings()
        {
            editBoxResourceFileName.Label = Properties.Resources.InputFileLabel;
            openButton.Label = Properties.Resources.OpenInputFileLabel;
            dropDownCultureNames.Label = Properties.Resources.CulturesLabel;
            buttonGenerate.Label = Properties.Resources.GenerateButtonLabel;
            buttonSync.Label = Properties.Resources.SyncButtonLabel;
            buttonPublish.Label = Properties.Resources.PublishButtonLabel;
            buttonSyncAll.Label = Properties.Resources.SyncAllButtonLabel;
            buttonSyncSelected.Label = Properties.Resources.SyncSelectedButtonLabel;
            buttonPublishAll.Label = Properties.Resources.PublishAllButtonLabel;
            buttonPublishSelected.Label = Properties.Resources.PublishSelectedButtonLabel;
            buttonReFillFromRoot.Label = Properties.Resources.RefillButtonLabel;
        }

        private void openButton_Click(object sender, RibbonControlEventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Filter = "Resoure Files (.resx)|*.resx|Excel files(.xlsx)|*.xlsx";
            DialogResult dialogResult = openFileDialog.ShowDialog();
            if (dialogResult == DialogResult.OK && !string.IsNullOrWhiteSpace(openFileDialog.FileName))
            {
                string resourceFile=string.Empty;

                // Validating the resource file if it is valid
                if (!string.IsNullOrWhiteSpace(resourceFile = CheckResourceFile(openFileDialog)))
                {
                    
                    if (ActivateNewExcelWorkbook(resourceFile))
                    {
                        CultureNames = new List<string>();
                        List<string> localizedResources = new List<string>(ResxParser.GetLocalizedFiles(resourceFile).ToList());
                        localizedResources.Insert(0, resourceFile);

                        for(int i=0;i<localizedResources.Count();i++)
                        {
                            SetCulturNames(localizedResources[i]);

                            Excel.Worksheet workSheet=Globals.ThisAddIn.Application.ActiveSheet;
                            workSheet = AddNewResourcesheet(localizedResources[i], i, workSheet);
                            if (i == 0)
                            {
                                RootResource = workSheet;
                               
                            }
                        }
                        if (RootResource != null) RootResource.Activate();
                        SetCultureNames();
                        EnableButtons(); 
                    }

                }
                else
                {
                    throw new Exception(Properties.Resources.ValidationError);
                }
            }
        }

      

        private static Excel.Worksheet AddNewResourcesheet(string localizedResource, int i, Excel.Worksheet workSheet)
        {
            workSheet = AddNewSheet(localizedResource, i, workSheet);

            UnprotectSheet(workSheet);

            SetFileNameInFirstRow(workSheet, localizedResource);

            FillCells(localizedResource, workSheet);
            ProtectSheet(workSheet);
            return workSheet;
        }

        private static void SetFileNameInFirstRow(Excel.Worksheet workSheet, string a)
        {
            workSheet.Cells[1, 1] = a;

            workSheet.Range["A1", "C1"].Merge();
        }

        private void SetCulturNames(string localizedResource)
        {
            string fileName = Path.GetFileName(localizedResource);
            if (fileName.Where(p => p == '.').Count() == 2)
            {
                CultureNames.Add(fileName.Split(new char[] { '.' })[1]);
            }
        }

        private static Excel.Worksheet AddNewSheet(string localizedResource,int i, Excel.Worksheet workSheet)
        {
            if (i > 0)
            {
                workSheet = Globals.ThisAddIn.Application.ActiveWorkbook.Worksheets.Add(After: workSheet);
                var tempsheetName=Path.GetFileName(localizedResource);
                if (tempsheetName.Where(p=>p=='.').Count()==2)
                {
                    tempsheetName = tempsheetName.Split(new char[] { '.' })[1];
                }
                int startIndex = tempsheetName.Length > 31 ? tempsheetName.Length - 31 : 0;
                workSheet.Name = tempsheetName.Substring(startIndex,tempsheetName.Length-startIndex);
                workSheet.Activate();
            }
            return workSheet;
        }

        private static void ProtectSheet(Excel.Worksheet workSheet)
        {
            workSheet.Protect("Protection");
        }

        private static void UnprotectSheet(Excel.Worksheet workSheet)
        {
            if (workSheet.ProtectContents)
            {
                workSheet.Unprotect("Protection");
            }
        }

        private static void FillCells(string localizedResource, Excel.Worksheet workSheet)
        {
            int rowIndex = 2;
            foreach (var resourceItems in ResxParser.ExtractFromFile(localizedResource))
            {
                workSheet.Cells[rowIndex, 1] = resourceItems.Name;                
                SetLock(workSheet, rowIndex, 1, true);

                workSheet.Cells[rowIndex, 2] = resourceItems.Value;
                SetLock(workSheet, rowIndex, 2, false);

                workSheet.Cells[rowIndex, 3] = resourceItems.Comment;
                SetLock(workSheet, rowIndex, 3, false);

                rowIndex++;

            }
            SetAutoFit(workSheet, rowIndex);
        }

        private static void SetAutoFit(Excel.Worksheet workSheet, int rowIndex)
        {
            try
            {
                Excel.Range firstColumn = (Excel.Range)workSheet.Range["A1", string.Format("A{0}", rowIndex)];
                firstColumn.Columns.AutoFit();
                firstColumn = (Excel.Range)workSheet.Range["B1", string.Format("B{0}", rowIndex)];
                firstColumn.ColumnWidth = 150;
                firstColumn = (Excel.Range)workSheet.Range["C1", string.Format("C{0}", rowIndex)];
                firstColumn.AutoFit();
            }
            catch { }
        }

        private static void SetLock(Excel.Worksheet workSheet, int rowIndex, int column, bool isLocked)
        {
            Excel.Range cell = (Excel.Range)workSheet.Cells[rowIndex, column];
            cell.Locked = isLocked;
        }

        private bool ActivateNewExcelWorkbook(string resourceFile)
        {
            Excel.Workbook previousExcel = Globals.ThisAddIn.Application.ActiveWorkbook;
            Globals.ThisAddIn.Application.ActiveWorkbook.Close();
            if (Globals.ThisAddIn.Application.ActiveWorkbook == null || Globals.ThisAddIn.Application.ActiveWorkbook != previousExcel)
            {
                Excel.Workbook newWoorkbook = Globals.ThisAddIn.Application.Workbooks.Add();
                newWoorkbook.Activate();
                if (newWoorkbook.Sheets.Count > 1)
                {
                    while (newWoorkbook.Sheets.Count!=1)
                    {
                        Excel.Worksheet ws = newWoorkbook.Sheets[1];
                        ws.Delete();
                    }
                    Excel.Worksheet worksheet = newWoorkbook.Sheets[1];
                    worksheet.Name = Path.GetFileName(resourceFile);
                    
                }
                editBoxResourceFileName.Text = resourceFile;
                RootResourceFile = resourceFile;
                RootResourceFileName = Path.GetFileName(resourceFile);
                return true;
            }
            return false;
        }

        private string CheckResourceFile(OpenFileDialog openFileDialog)
        {
            if (CheckIfFileIsResourceFile(openFileDialog.FileName))
            {
                string resourceFileDirectory = GetDirectory(openFileDialog.FileName);
                string rootResourceFileName = GetRootResourceFileName(openFileDialog.FileName);
                if (string.IsNullOrWhiteSpace(rootResourceFileName))
                {
                    MessageBox.Show(Properties.Resources.WrongResourceFile);
                }
                else
                {
                    if (CheckIfFileexists(resourceFileDirectory, rootResourceFileName))
                    {
                        return Path.Combine(resourceFileDirectory, rootResourceFileName);
                    }
                }
            }
            else
            {
                MessageBox.Show(Properties.Resources.WrongResourceFile);
            }
            return string.Empty;
        }

        private string GetDirectory(string p)
        {
            return Path.GetDirectoryName(p);
        }

        private bool CheckIfFileexists(string directory, string rootResourceFileName)
        {
            return File.Exists(Path.Combine(directory, rootResourceFileName));
        }

        private string GetRootResourceFileName(string p)
        {
            var fileName=Path.GetFileName(p);
            if (fileName.Where(z => z == '.').Count() == 1)
            {
                return fileName;
            }
            else
            {
                var splitted = fileName.Split(new char[] { '.' });
                if (splitted.Count() != 3)
                {
                    return string.Empty;
                }
                else
                {
                    return string.Format("{0}.{1}", splitted[0], splitted[2]);
                }
            }
        }

        private bool CheckIfFileIsResourceFile(string p)
        {
            return Path.GetExtension(p).ToLower().Equals(".resx");
        }

        private void buttonGenerate_Click(object sender, RibbonControlEventArgs e)
        {
            
            var newFilePath = ResxParser.CreateResource(RootResourceFile, dropDownCultureNames.SelectedItem.Tag.ToString());

            AddNewResourcesheet(newFilePath, 2, GetLastSheet());            
            
        }

        private static Excel.Worksheet GetLastSheet()
        {
            return Globals.ThisAddIn.Application.ActiveWorkbook.Sheets[Globals.ThisAddIn.Application.ActiveWorkbook.Sheets.Count];
        }

        private bool SyncWithRootResource(Excel.Worksheet newWorksheet)
        {
            try
            {
                if (RootResource != null)
                {
                    int rowIndex = 2;
                    while (!string.IsNullOrWhiteSpace(((Excel.Range)RootResource.Cells[rowIndex, 1]).Text))
                    {
                        CopyCell(newWorksheet, rowIndex, 1);
                        SetLock(newWorksheet, rowIndex, 1, true);

                        CopyCell(newWorksheet, rowIndex, 2);
                        SetLock(newWorksheet, rowIndex, 2, false);

                        CopyCell(newWorksheet, rowIndex, 3);
                        SetLock(newWorksheet, rowIndex, 3, false);

                        rowIndex++;
                    }
                    SetAutoFit(newWorksheet, rowIndex);
                }
            }
            catch (Exception ex)
            {
                return false;
            }
            return true;
        }

        private void CopyCell(Excel.Worksheet newWorksheet, int rowIndex, int column)
        {
            newWorksheet.Cells[rowIndex, column] = RootResource.Cells[rowIndex, column];
        }

        private void buttonReFillFromRoot_Click(object sender, RibbonControlEventArgs e)
        {
            bool result = true;
            if (MessageBox.Show(Properties.Resources.ConfirmRefill, APPLICATION_NAME, MessageBoxButtons.YesNo, MessageBoxIcon.Question)==DialogResult.Yes)
            {
                if (RootResource != null && Globals.ThisAddIn.Application.ActiveSheet != RootResource)
                {
                    Excel.Worksheet activeSheet = Globals.ThisAddIn.Application.ActiveSheet;

                    string fileName = GetStringValue(activeSheet, 1, 1);
                    UnprotectSheet(activeSheet);

                    activeSheet.Cells.Clear();
                    SetFileNameInFirstRow(activeSheet, fileName);
                    result = SyncWithRootResource(activeSheet);
                    ProtectSheet(activeSheet);
                }
            }
            if (!result)
            {
                MessageBox.Show(Properties.Resources.FailedSync, APPLICATION_NAME, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private static string GetStringValue(Excel.Worksheet activeSheet, int row, int column)
        {
            Excel.Range objRange = (Excel.Range)activeSheet.Cells[row, column];
            return objRange.get_Value(Missing.Value) == null ? string.Empty : objRange.get_Value(Missing.Value).ToString();
        }

      

        private void buttonSyncSelected_Click(object sender, RibbonControlEventArgs e)
        {
            if (MessageBox.Show(Properties.Resources.ConfirmSync, APPLICATION_NAME, MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
            {
                Excel.Worksheet activeSheet = Globals.ThisAddIn.Application.ActiveSheet;
                SyncSelectedSheet(activeSheet);
            }
        }

        private static void SyncSelectedSheet(Excel.Worksheet activeSheet)
        {
            string resourceFileName = GetStringValue(activeSheet, 1, 1);
            if (!string.IsNullOrWhiteSpace(resourceFileName))
            {
                UnprotectSheet(activeSheet);
                activeSheet.Cells.Clear();
                SetFileNameInFirstRow(activeSheet, resourceFileName);

                FillCells(resourceFileName, activeSheet);
                ProtectSheet(activeSheet);
            }
        }

        private void buttonPublishSelected_Click(object sender, RibbonControlEventArgs e)
        {
            if (MessageBox.Show(Properties.Resources.ConfirmPublish, "Resx Converter", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
            {
                Excel.Worksheet activeSheet = Globals.ThisAddIn.Application.ActiveSheet;
                bool resultValue = PublishSheet(activeSheet);
                if (resultValue)
                {
                    MessageBox.Show(Properties.Resources.MessagePublishedSuccessfully);
                }
            }
            
        }

        private static bool PublishSheet(Excel.Worksheet activeSheet)
        {
            var fileName = GetStringValue(activeSheet, 1, 1);
            int i = 2;
            Dictionary<string, Tuple<string, string>> resourceItems = new Dictionary<string, Tuple<string, string>>();
            while (!string.IsNullOrWhiteSpace(GetStringValue(activeSheet, i, 1)))
            {
                resourceItems.Add(GetStringValue(activeSheet, i, 1), new Tuple<string, string>(GetStringValue(activeSheet, i, 2), GetStringValue(activeSheet, i, 3)));
                i++;
            }
            bool resultValue = ResxParser.ReWriteResourceFile(fileName, resourceItems);
            return resultValue;
        }

        private void editBoxResourceFileName_TextChanged(object sender, RibbonControlEventArgs e)
        {

            EnableButtons();
        }

        private void EnableButtons()
        {
            buttonGenerate.Enabled = buttonPublish.Enabled = buttonSync.Enabled = editBoxResourceFileName.Text.Length > 0;
        }

        private void buttonPublishAll_Click(object sender, RibbonControlEventArgs e)
        {
            bool? returnValue = null;
            if (MessageBox.Show(Properties.Resources.ConfirmAllPublish,"Resx Converter",MessageBoxButtons.YesNo,MessageBoxIcon.Question) == DialogResult.Yes)
            {
                foreach (Excel.Worksheet item in Globals.ThisAddIn.Application.ActiveWorkbook.Sheets)
                {
                    if (item != this.RootResource)
                    {
                        if (!PublishSheet(item))
                        {
                            returnValue = false;
                        }
                    }
                }
            }
            if (returnValue.HasValue && !returnValue.Value)
            {
                MessageBox.Show(Properties.Resources.FailedSync, "Resx Converter", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            else
            {
                MessageBox.Show(Properties.Resources.MessagesPublishedSuccessfully, "Resx Converter", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }

        private void buttonSyncAll_Click(object sender, RibbonControlEventArgs e)
        {
            if (MessageBox.Show(Properties.Resources.ConfirmAllSync, APPLICATION_NAME, MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
            {
                foreach (Excel.Worksheet item in Globals.ThisAddIn.Application.ActiveWorkbook.Sheets)
                {
                    if (item != this.RootResource)
                    {
                        SyncSelectedSheet(item);
                    }
                }
            }
        }
    }
}
